import json
import logging
import os

import requests
import static
from common.enums.common_enums import TokenType
from common.utils.config_util import EnvConfig
from common.utils.file_util import CacheUtil
from common.utils.string_util import StringUtil
from common.utils import param_util

logger = logging.getLogger(__name__)


class TokenUtil:
    def __init__(self, token_type: TokenType):
        if not isinstance(token_type, TokenType):
            raise ValueError('token_type必须为枚举类成员！')
        self.token_type = token_type

    def get_token(self):
        if self.token_type == TokenType.RABBIT_PLATFORM_TOKEN:
            token = self.get_rabbit_platform_token()
        else:
            pass
        return token

    def get_rabbit_platform_token(self, *, role='system', username=None, password=None):
        env_config = EnvConfig.get_config()
        url = env_config['host']['rabbit_platform'] + static.UriConfig.RABBIT_PLATFORM_LOGIN_URI
        if not (username and password):
            username = env_config['account'][role]['username']
            password = env_config['account'][role]['password']
        data = {
            "username": username,
            "password": password
        }
        token_type = self.token_type.value
        try:
            response = requests.post(url, data=data).json()
            token = response['result'][token_type]
        except KeyError:
            logger.error('获取不到token!')
            raise
        except Exception:
            logger.error('请求发送失败!')
            raise
        return {token_type: token}

    def get_hroj_token(self):
        pass


class HttpHeaders:
    common_headers = {'User-Agent': 'firefox'}
    token_headers = {}

    @classmethod
    def get_headers(cls, *, token_type=None):
        if not token_type:
            return HttpHeaders.common_headers
        else:
            if not HttpHeaders.token_headers:
                token = TokenUtil(token_type).get_token()
                HttpHeaders.token_headers.update(HttpHeaders.common_headers)
                HttpHeaders.token_headers.update(token)
            return HttpHeaders.token_headers.copy()


class HttpRequest:
    def __init__(self, url, method, data, *, param_type=None, headers):
        self.url = url
        self.method = method
        self.data = data
        self.param_type = param_type
        self.headers = headers

    def do_request(self):
        response = {}
        method = str(self.method).lower()
        if method not in ['get', 'post', 'put', 'delete']:
            raise ValueError(f'请求方式:{method}不正确！')
        if self.param_type and str(self.param_type).lower() not in ['form', 'json', 'file']:
            raise ValueError(f'参数类型:{self.param_type}不正确！')
        if method == 'get':
            response = requests.get(self.url, params=self.data, headers=self.headers).json()
        elif method == 'post':
            if self.param_type == 'form':
                self.headers.update({'Content-Type': 'application/x-www-form-urlencoded'})
                response = requests.post(self.url, data=self.data, headers=self.headers).json()
            elif self.param_type == 'json':
                self.headers.update({'Content-Type': 'application/json;charset=utf8'})
                response = requests.post(self.url, json=self.data, headers=self.headers).json()
            elif self.param_type == 'file':
                if not self.data.get('file_path'):
                    raise ValueError('file_path不能为空！')
                if not self.data.get('file_key'):
                    raise ValueError('file_key不能为空！')
                file_path = self.data['file_path']
                file_key = self.data['file_key']
                self.data.pop('file_path')
                self.data.pop('file_key')
                # multipate请求一定不要加Content-Type请求头,会请求失败
                # self.headers.update({'Content-Type': 'multipart/form-data; boundary=<calculated when request is
                # sent>'})
                files = {file_key: open(file_path, 'rb')}
                content_type = self.headers.get('Content-Type')
                if not self.data:
                    response = requests.post(self.url, files=files, headers=self.headers).json()
                else:
                    response = requests.post(self.url, data=self.data, files=files, headers=self.headers).json()
        elif method == 'put':
            if self.param_type == 'json':
                self.headers.update({'Content-Type': 'application/json;charset=utf8'})
                response = requests.put(self.url, json=self.data, headers=self.headers).json()
            else:
                raise ValueError('put请求的param_type只能为json类型!')
        return response


def do_simple_request(case, *, token_type=None, cache_key=None):
    env_config = EnvConfig.get_config()
    url = env_config['host'][case['host']] + case['path']
    param_type = case['param_type']
    # 处理参数
    params = ''
    # todo:get请求参数化
    if str(case['method']).lower() == 'get':
        params = case['params']
    else:
        params = json.loads(case['params']) if case['params'] else {}
        param_util.deal_params(params, cache_key=cache_key)
    if param_type == 'file':
        if not case['file_path']:
            raise ValueError('file_path不能为空！')
        if not case['file_key']:
            raise ValueError('file_key不能为空！')
        # 设置上传文件目录
        file_path = os.path.join(static.PROJECT_PATH, 'test_data', case['host'], 'files', case['file_path'])
        params.update({'file_path': file_path})
        params.update({'file_key': case['file_key']})
    logger.info(f"请求参数为：{params}")
    response = HttpRequest(url, case['method'], params, param_type=param_type,
                           headers=HttpHeaders.get_headers(token_type=token_type)).do_request()
    return response


if __name__ == '__main__':
    # token = get_token(username='admin' ,password='admin1')
    # print(token)
    # no_token_headers = HttpHeaders.get_headers()
    # token_headers1 = HttpHeaders.get_headers(need_token=True)
    # token_headers2 = HttpHeaders.get_headers(need_token=True)
    # print(f'no_token_headers={no_token_headers}')
    # print(f'token_headers1={token_headers1}')
    # print(f'token_headers1是否等于token_headers2:{token_headers1 == token_headers2}')
    config = EnvConfig.get_config()
    url1 = config['host']['rabbit_platform'] + static.UriConfig.RABBIT_PLATFORM_LOGIN_URI
    data1 = {
        "username": 'admin',
        "password": 'admin1'
    }
    response1 = HttpRequest(url1, 'post', json.dumps(data1), param_type='form',
                            headers=HttpHeaders.get_headers()).do_request()
    print(f'response1={response1}')
    # url2 = config['host']['user_interface'] + static.UriConfig.USER_INTERFACE_LOGIN_URI
    # data2 = {
    #     "username": 'Jack',
    #     "passwd": '111222'
    # }
    # response2 = HttpRequest(url2, 'post', json.dumps(data2), param_type='json',
    #                         headers=HttpHeaders.get_headers()).do_request()
    # print(f'response2={response2}')
    # # 查询api接口
    # url3 = config['host']['rabbit_platform'] + static.UriConfig.RABBIT_PLATFORM_QUERY_API_URI
    # data3 = {"pageNum": 1, "pageSize": 10, "serchData": ""}
    # response3 = HttpRequest(url1, 'get', json.dumps(data3), headers=HttpHeaders.get_headers()).do_request()
    # print(f'response3={response3}')
